﻿using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Controllers;
using StarsAdmin.Core.App;
using StarsAdmin.Core.Cache;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace StarsAdmin.Core.Extensions
{
    public static class XmlParser
    {
        // 缓存键
        private static readonly string _key = "XML_DOCUMENT_PARSER";

        //缓存时间
        private static readonly int _expire = 5;

        private static readonly ICacheService _cache = AppHelper.GetService<ICacheService>();

        private static async Task<Dictionary<string, string>> InitXmlParserAsync()
        {
            var xml = new Dictionary<string, string>();
            if (!_cache.Validate(_key))
            {
                // 获得程序入口程序集
                var assembly = Assembly.GetEntryAssembly();
                if (assembly != null)
                {
                    string xmlFilename = $"{assembly?.GetName().Name}.xml";
                    var path = Path.Combine(AppContext.BaseDirectory, xmlFilename);
                    xml = await path.ParseXmlAsnyc();
                }
            }
            return xml;
        }

        public static async Task<string> GetXmlDocsCommentsAsync(this TypeInfo typeinfo)
        {
            Dictionary<string, string> xmldocs = await _cache.GetOrSetAsync(_key, InitXmlParserAsync, _expire);
            var name = xmldocs.TryGetValue(typeinfo.FullName, out var value) ? value.ToString() : null;
            return name ?? "";
        }

        public static async Task<string> GetXmlDocsCommentsAsync(this string fullName)
        {
            Dictionary<string, string> xmldocs = await _cache.GetOrSetAsync(_key, InitXmlParserAsync, _expire);
            var name = xmldocs.TryGetValue(fullName.Trim(), out var value) ? value.ToString() : "";
            return name;
        }

        public static async Task<string> GetXmlDocsCommentsAsync(this IGrouping<string, ApiDescription> controller)
        {
            var controllerType = ((ControllerActionDescriptor)controller.First().ActionDescriptor).ControllerTypeInfo;
            return await controllerType.GetXmlDocsCommentsAsync();
        }

        public static async Task<Dictionary<string, string>> ParseXmlAsnyc(this string xmlFilePath)
        {
            // 载入xml文档
            XDocument doc = XDocument.Load(xmlFilePath);
            Dictionary<string, string> apis = new Dictionary<string, string>();
            var xmlELements = doc.Descendants("member");
            foreach (var member in xmlELements)
            {
                string memberName = member.Attribute("name").Value;

                if (memberName.StartsWith("T:")) // 控制器
                {
                    var controllerName = memberName.Substring(2);
                    var summary = member.Element("summary")?.Value.CleanComment();
                    apis.Add(controllerName, summary);
                } else if (memberName.StartsWith("M:")) // 方法
                {
                    var methodName = memberName.Substring(2).Split('(').First();
                    var summary = member.Element("summary")?.Value.CleanComment();
                    apis.Add(methodName, summary);

                    // 暂时不需要解析参数注释，及返回值注释
                    //foreach (var item in member.Elements("param"))
                    //{
                    //    string paramValueName = item.Attribute("name").Value;
                    //    var paramName = memberName.Substring(2).Split('(').Last().Split(')').First();
                    //    var param = item?.Value.CleanComment();
                    //    if (!paramName.IsNullOrWhiteSpace())
                    //    {
                    //        apis.Add(methodName + "/" + paramValueName, param);
                    //    }
                    //}
                    // var returns = member.Element("returns")?.Value.CleanComment();
                }
            }
            return await Task.FromResult(apis);
        }

        private static string CleanComment(this string comment)
        {
            // 去除首尾空白字符
            comment = comment.Trim();
            // 使用正则表达式去除多余的空格
            comment = Regex.Replace(comment, @"\s+", " ");
            // 根据需要标准化换行符
            // 例如，将所有换行符替换为单个空格
            comment = comment.Replace("\r", " ").Replace("\n", " ").Trim();
            return comment;
        }
    }
}